#!/usr/bin/python
# -*- coding: utf-8 -*-
# @Project    : AutomatedTesting
# @Name       : scheduler.py
# @IDE        : PyCharm
# @Author     : OneYoung
# @Created    : 2025/8/25 10:18
# @Desc       : 定时任务调度器

from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.interval import IntervalTrigger
from typing import Callable, Any, Dict, Union


class Scheduler:
    def __init__(self):
        self.scheduler = BackgroundScheduler(
            jobstores={'default': MemoryJobStore()},
            timezone='Asia/Shanghai'
        )
        self._init_scheduler()

    def _init_scheduler(self):
        """初始化调度器配置"""
        self.scheduler.configure()
        self.scheduler.start()

    def add_date_job(self,
                     func: Callable,
                     run_date: Union[datetime, str],
                     args: list | tuple = None,
                     job_id: str = None) -> str:
        """
        添加一次性定时任务

        :param func: 要执行的函数
        :param run_date: 执行时间(datetime对象或ISO格式字符串)
        :param args: 函数参数
        :param job_id: 自定义任务ID
        :return: 任务ID
        """
        if isinstance(run_date, str):
            run_date = datetime.fromisoformat(run_date)

        trigger = DateTrigger(run_date=run_date)
        job = self.scheduler.add_job(
            func,
            trigger=trigger,
            args=args,
            id=job_id
        )
        return job.id

    def add_cron_job(self,
                     func: Callable,
                     cron_expr: Dict[str, str],
                     args: list | tuple = None,
                     job_id: str = None) -> str:
        """
        添加Cron表达式定时任务

        :param func: 要执行的函数
        :param cron_expr: Cron参数字典，例如：
            {
                'year': '2025',
                'month': '1-12',
                'day_of_week': '0-6 or mon,tue,wed,thu,fri,sat,sun',
                'day': '1-31',
                'hour': '0-23',
                'minute': '0-59'
                'second': '0-59'
            }
        :param args: 函数参数
        :param job_id: 自定义任务ID
        """
        trigger = CronTrigger(**cron_expr)
        job = self.scheduler.add_job(
            func,
            trigger=trigger,
            args=args,
            id=job_id
        )
        return job.id

    def add_interval_job(self,
                         func: Callable,
                         interval: Dict[str, int],
                         args: list | tuple = None,
                         job_id: str = None
                         ) -> str:
        """
        添加间隔定时任务

        :param func: 要执行的函数
        :param interval: 间隔参数字典，例如：
            {'weeks': 1, 'days': 2, 'hours': 3, "minutes": 4, "seconds": 5}
        :param args: 函数参数
        :param job_id: 自定义任务ID
        """
        trigger = IntervalTrigger(**interval)
        job = self.scheduler.add_job(
            func,
            trigger=trigger,
            args=args,
            id=job_id
        )
        return job.id

    def run_job_immediately(self, func: Callable, args: list | tuple = None) -> str:
        """
        立即执行任务

        :param func: 要执行的函数
        :param args: 函数参数
        """
        return self.add_date_job(
            func=func,
            run_date=datetime.now(),
            args=args
        )

    def get_job_info(self, job_id: str) -> Dict[str, Any]:
        """
        获取任务详细信息

        :param job_id: 自定义任务ID
        """
        job = self.scheduler.get_job(job_id)
        return {
            'id': job.id,
            'name': job.name,
            'next_run_time': job.next_run_time.strftime("%Y-%m-%d %H:%M:%S"),
            'trigger': str(job.trigger)
        }

    def remove_job(self, job_id: str):
        """移除指定任务"""
        self.scheduler.remove_job(job_id)

    def shutdown(self):
        """关闭调度器"""
        self.scheduler.shutdown()
